package battleship.data;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import battleship.Controller;
import battleship.Loop;
import battleship.PluginAI;
import battleship.Setup;
import battleship.field.Field;
import battleship.loop.MoveCollisionException;
import battleship.loop.OutOfSpaceException;
import battleship.player.Player;

public class SaveLoader {
	
	Document doc;
	
	private int field_height;
	private int field_width;
	private int turns;

	private String playerNames[];
	private boolean playerBot[];
	private String[][] playerBoats;
	private String[][] playerField;
	
	public SaveLoader() throws SAXException, IOException, ParserConfigurationException
	{
		File file = SaveXML.FILE;
		
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		
		this.doc = db.parse(file);
	}
	
	public boolean LoadField()
	{
		try
		{
			
			field_height = Integer.valueOf(doc.getElementsByTagName("height").item(0).getTextContent());
			field_width = Integer.valueOf(doc.getElementsByTagName("width").item(0).getTextContent());
			turns = Integer.valueOf(doc.getElementsByTagName("turns").item(0).getTextContent());

			playerNames = new String[2];
			playerBot = new boolean[2];

			playerBoats = new String[2][5];
			playerField = new String[2][];
			
			NodeList names = doc.getElementsByTagName("name");
			NodeList bots = doc.getElementsByTagName("isBot");
			NodeList hits = doc.getElementsByTagName("hits");
			NodeList[] boatsPlayer = new NodeList[5];
			
			for(int boat = 0; boat < boatsPlayer.length; ++boat)
			{
				boatsPlayer[boat] = doc.getElementsByTagName(SaveXML.BOATNAMES[boat]);
			}
			
			

			for(int player = 0; player < doc.getElementsByTagName("name").getLength(); ++player)
			{
				playerNames[player] = names.item(player).getTextContent();
				playerBot[player] = bots.item(player).getTextContent().equals("true");

				for(int boat = 0; boat < boatsPlayer.length; ++boat)
				{
					playerBoats[player][boat] = 
						boatsPlayer[boat].item(player).getTextContent();
				}
				
				String[] fieldHits = hits.item(player).getTextContent().split(", ");
				
				ArrayList<String> fieldHitsToString = new ArrayList<String>();
				
				for(int height = 0; height < field_height; ++height)
				{
					for (int width = 0; width < field_width; ++width)
					{
						if(fieldHits[height].charAt(width) == '1')
						{
							StringBuilder position = new StringBuilder(0);
							String x = String.valueOf(width + 1);
							String y = Setup.getPositionMap()[height];
							
							position.append(y);
							position.append(x);
							
							fieldHitsToString.add(position.toString());
						}
					}
				}
				if(fieldHitsToString.size() != 0)
				{
					playerField[player] = new String[fieldHitsToString.size()];
					fieldHitsToString.toArray(playerField[player]);
				}
				else
				{
					playerField[player] = new String[] {};
				}
			}
		}
		catch (Exception e)
		{

			return false;
		}
		
		return true;
	}
	
	public String[] getNames()
	{
		return playerNames;
	}
	
	
	public void injectData()
	{
		for(int player = 0; player < playerNames.length; ++player)
		{
			Setup.getPlayers()[player] = new Player(playerNames[player], playerBot[player]);
			
			if(playerBot[player])
			{
				for(PluginAI plug : Controller.getPluginsAI())
				{
					if(plug.getName().equals(playerNames[player]))
					{
						Setup.getPlayers()[player].setAI(plug);
						break;
					}
				}
			}
			
			
		}
		
		// set field sizes and turns done
		Field.setHeight(field_height);
		Field.setWidth(field_width);
		Loop.setTurns(turns);
		//set the last player to have attacked
		Loop.setLastTurn(getLastPlayer());
		
		for(int player = 0; player < playerNames.length; ++player)
		{
			
			
			// set the boats
			for(int boat = 0; boat < playerBoats[player].length; ++boat)
			{
				Setup.setBoat(Setup.getPlayers()[player],
						Setup.getPlayers()[player].getField().getBoats()[boat], 
						playerBoats[player][boat]);
			}
		}
		
		for(int player = 0; player < Setup.getPlayers().length; ++player)
		{
			for(int hit = 0; hit < playerField[(player + 1) % 2].length; ++hit)
			{
				try {
					Setup.getPlayers()[player].strike(playerField[(player + 1) % 2][hit]);
					
					
					
				} catch (IllegalArgumentException e) {
					// shouldn't happen
					e.printStackTrace();
				} catch (MoveCollisionException e) {
					// shouldn't happen
					e.printStackTrace();
				} catch (OutOfSpaceException e) {
					// shouldn't happen
					e.printStackTrace();
				}
			}
			
			
		}
		
	}
	
	private Player getLastPlayer()
	{
		
		return Setup.getPlayers()[(turns + 1) % 2];
		
	}
	
	public String toString()
	{
		StringBuilder output = new StringBuilder();
		output.append("Field Width: " + field_width + '\n');
		output.append("Field Height: " + field_height + '\n');
		output.append("Turns: " + turns + '\n');
		
		for(int player = 0; player < playerNames.length; ++player)
		{
			output.append("\tPlayer: " + playerNames[player] + '\n');
			
			output.append("\tBot: ");
			output.append(playerBot[player]);
			output.append('\n');
			
			output.append("Boats: ");
			for(int boat = 0; boat < playerBoats[player].length; ++boat)
			{
				output.append(playerBoats[player][boat] + ", ");
			}
			output.append('\n');
			
			output.append("Field: ");
			for(int hit = 0; hit < playerField[player].length; ++hit)
			{
				output.append(playerField[player][hit] + ", ");
			}
			output.append('\n');
		}
		return output.toString();
	}
}
